package com.apes.scm.rbac.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.query.SqlService;
import com.apes.framework.util.MapUtil;
import com.apes.scm.rbac.model.ApplyRole;
import com.apes.scm.rbac.model.ApplyRoleItem;
import com.apes.scm.rbac.model.Operation;
import com.apes.scm.rbac.multiKeys.MenuOperationKey;
import com.apes.scm.rbac.repository.ApplyRoleRepository;
import com.apes.scm.rbac.repository.MenuRepository;
import com.apes.scm.rbac.repository.OperationRepository;
import com.apes.scm.rbac.repository.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 角色申请单
 * Created by lishikun on 2021/4/30 9:16
 */
@Service("applyRoleService")
public class ApplyRoleService extends DomainService {

    @Autowired
    private ApplyRoleRepository applyRoleRepository;

    @Autowired
    private SequenceService sequenceService;
    
    @Autowired
    private SqlService sqlService;
    @Autowired
    private MenuRepository menuRepository;
    @Autowired
    private RoleRepository roleRepository;
    public ApplyRole create(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        applyRole.setCreator(getPersonId(request));
        applyRole.setCreateDate(new Date());
        if (applyRole.getId() == null) {
            applyRole.setId(sequenceService.getId(ApplyRole.CONST_TABLE_NAME));
        }
        checkAuthority(applyRole);
        return applyRoleRepository.saveAndFlush(applyRole);
    }

    public ApplyRole save(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        checkAuthority(applyRole);
        return applyRoleRepository.saveAndFlush(applyRole);
    }

    public String delete(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        applyRoleRepository.delete(applyRole);
        return "删除成功";
    }

    public Map findOperation(SimpleRequest request) {
        JSONArray filters = request.getJO().getJSONObject("group").getJSONArray("filters");
        JSONArray value = null;
        for (Object o : filters) {
            JSONObject filter = (JSONObject) o;
            if ("menu".equals(filter.get("field"))) {
                value = filter.getJSONArray("value");
            }
            if ("menuOperations".equals(filter.get("field")) && filter.get("value") != null) {
                value = filter.getJSONArray("value");
            }
        }
        return mapper("content", value,
                "total", 1,
                "pages", 1,"size", value == null ? 0 :value.size(), "elements", 1, "page", 0);
    }

    private void checkAuthority(ApplyRole applyRole) {
        /**
         * 1.找菜单权限(删除操作)
         * 2.找增加的权限（增加操作）
         * 3.找减少的权限（减少操作）
         */
        List<ApplyRoleItem> applyRoleItems = applyRole.getApplyRoleItems();
        if (applyRoleItems != null) {

        }
        for (ApplyRoleItem applyRoleItem : applyRoleItems) {
            applyRole.getRole().getOperations();
            // 删除
            if (applyRoleItem.getDeleteMenu()) {
                Boolean deleteOperation = false;
                for (Operation operation : applyRole.getRole().getOperations()) {
                    if (operation.getMenu().getId() == applyRoleItem.getMenu().getId()) {
                        deleteOperation = true;
                    }
                }
                if (!deleteOperation) throw new RuntimeException("无该菜单权限无法删除");
            }

            // 增加
            List addOperations = applyRoleItem.getAddOperations();
            if (addOperations != null) {
                for (Object add : addOperations) {
                    Operation  addOperation = JSON.toJavaObject((JSONObject)add, Operation.class);
                    if (applyRole.getRole().getOperations().stream().filter(
                            operation1 -> operation1.getMenu().getId() == applyRoleItem.getMenu().getId() &&
                                    operation1.getOperationId().equals(addOperation.getOperationId()))
                            .count() > 0)
                        throw new RuntimeException("已有该按钮权限无法增加");
                }
            }


            // 减少
            List reduceOperations = applyRoleItem.getReduceOperations();
            if (reduceOperations != null) {
                for (Object reduce : reduceOperations) {
                    Operation reduceOperation = JSON.toJavaObject((JSONObject)reduce, Operation.class);
                    if (applyRole.getRole().getOperations().stream().filter(
                            operation1 -> operation1.getMenu().getId() == applyRoleItem.getMenu().getId() &&
                                    operation1.getOperationId().equals(reduceOperation.getOperationId()))
                            .count() == 0) {
                        throw new RuntimeException("无该按钮权限无法减少");
                    }
                }
            }

        }

    }

    public void approve(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        List<ApplyRoleItem> applyRoleItems = applyRole.getApplyRoleItems();
        Set<Operation> operations = applyRole.getRole().getOperations();
        for (ApplyRoleItem applyRoleItem : applyRoleItems) {
            applyRole.getRole().getOperations();
            // 删除
            if (applyRoleItem.getDeleteMenu()) {
                Boolean deleteOperation = false;

                Set<Operation> o = new HashSet<>();
                for (Operation operation : operations) {
                    if (operation.getMenu().getId() == applyRoleItem.getMenu().getId()) {
                        MenuOperationKey key = new MenuOperationKey();
                        key.setMenu(Integer.parseInt(applyRoleItem.getMenu().getId().toString()));
                        key.setOperationId(operation.getOperationId());
                        Operation one = SpringManager.getBean(OperationRepository.class).findOne(key);
                        one.getRoles().add(applyRole.getRole());
                        o.add(one);
                    }
                }
                operations.removeAll(o);
            }

            // 增加
            List addOperations = applyRoleItem.getAddOperations();
            if (addOperations != null) {
                Set<Operation> o = new HashSet<>();
                for (Object add : addOperations) {
                    Operation addOperation = JSON.toJavaObject((JSONObject)add, Operation.class);
                    if (applyRole.getRole().getOperations().stream().filter(
                            operation1 -> operation1.getMenu().getId() == applyRoleItem.getMenu().getId() &&
                                    operation1.getOperationId().equals(addOperation.getOperationId()))
                            .count() <= 0 ) {
                        MenuOperationKey key = new MenuOperationKey();
                        key.setMenu(Integer.parseInt(applyRoleItem.getMenu().getId().toString()));
                        key.setOperationId(addOperation.getOperationId());
                        Operation one = SpringManager.getBean(OperationRepository.class).findOne(key);
                        one.getRoles().add(applyRole.getRole());
                        o.add(one);
                    }
                }
                operations.addAll(o);
            }

            List reduceOperations = applyRoleItem.getReduceOperations();
            // 减少
            if (reduceOperations != null) {
                Set<Operation> o = new HashSet<>();
                for (Object reduce : reduceOperations) {
                    Operation reduceOperation = JSON.toJavaObject((JSONObject)reduce, Operation.class);
                    if (applyRole.getRole().getOperations().stream().filter(
                            operation1 -> operation1.getMenu().getId() == applyRoleItem.getMenu().getId() &&
                                    operation1.getOperationId().equals(reduceOperation.getOperationId()))
                            .count() > 0) {
                        MenuOperationKey key = new MenuOperationKey();
                        key.setMenu(Integer.parseInt(applyRoleItem.getMenu().getId().toString()));
                        key.setOperationId(reduceOperation.getOperationId());
                        Operation one = SpringManager.getBean(OperationRepository.class).findOne(key);
                        one.getRoles().add(applyRole.getRole());
                        o.add(one);
                    }
                }
                operations.removeAll(o);
            }
            applyRole.setState("finish");
            applyRole.setApproveId(getPerson(request));
            applyRole.setApproveDate(new Date());
            roleRepository.saveAndFlush(applyRole.getRole());
        }
        SpringManager.getBean(RoleService.class).removeMenuAuth(applyRole.getRole());
        applyRoleRepository.saveAndFlush(applyRole);
    }



    public Map find(SimpleRequest request) throws Exception {
        JSONObject param = request.getJO();
        param.put("page", param.getIntValue("page") + 1);
        com.apestech.framework.json.JSONArray jsonArray = sqlService.queryId("applyRole.query", new com.apestech.framework.json.JSONObject(param));
        com.apestech.framework.json.JSONObject jsonObject = jsonArray.getJSONObject(0).getJSONObject("SYS_PAGE");
        List<Object> list= jsonArray.subList(1, jsonArray.size());
        List newList= new ArrayList();
        for (Object o : list) {
            JSONObject json = JSON.parseObject(o.toString());
            JSONArray reduceArray = JSONArray.parseArray(json.getString("REDUCE_OPERATION"));
            JSONArray addArray = JSONArray.parseArray(json.getString("ADD_OPERATION"));

            String reduceOperation = "";
            String addOperation = "";
            if (reduceArray != null) {
                for (Object o1 : reduceArray) {
                    JSONObject jsonObject1 = (JSONObject) o1;
                    reduceOperation += jsonObject1.getString("name") +";";
                }
            }
            if (addArray != null) {
                for (Object o1 : addArray) {
                    JSONObject jsonObject1 = (JSONObject) o1;
                    addOperation += jsonObject1.getString("name") +";";
                }
            }
            json.put("reduceOperation", reduceOperation);
            json.put("addOperation", addOperation);
            newList.add(json);
        }
        return MapUtil.mapper("content", newList, "elements", newList.size(),
                "total", jsonObject.getInteger("Total"),
                "pages", jsonObject.getInteger("TotalPage"),
                "size", jsonObject.getInteger("Size"),
                "page", jsonObject.getInteger("Page") - 1);
    }

    public ApplyRole findOne(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        if (Objects.isNull(applyRole.getApplyRoleItems())) return null;
        for (ApplyRoleItem applyRoleItem : applyRole.getApplyRoleItems()) {
            applyRoleItem.setMenu(SpringManager.getBean(MenuRepository.class).findOne(applyRoleItem.getMenu().getId()));
        }
        return applyRole;
    }


    // 拒绝
    public ApplyRole refuse(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        applyRole.setState("sent");
        return applyRoleRepository.saveAndFlush(applyRole);
    }

    public ApplyRole turnApprove(SimpleRequest request) {
        ApplyRole applyRole = request.getO(ApplyRole.class);
        applyRole.setState("approve");
        return applyRoleRepository.saveAndFlush(applyRole);
    }
}

